-- MySQL高级查询
-- select ... 聚合函数 from 表名 where ... group by ... having ... order by ... limit ...
-- order by 给查询结果排序：ASC：默认，升序、DESC：降序
-- limit 显示查询记录的条数
-- limit放在查询语句的最后，后边不再放其他的语句。
-- 用法：
-- limit n; —–> 显示 n 条记录
-- limit m， n; —–> 从第(m+1)条记录开始，显示 n 条记录
-- limit 分页
-- 要求每页显示 n 条记录，显示第 4 页的内容：limt (4-1)*n,n
-- 聚合函数：
-- avg(字段名)：求该字段的平均值
-- sum(字段名)：求和
-- max(字段名)：求最大值
-- min(字段名)：求最小值
-- count(字段名)：统计该字段的记录的条数
select count(empno) from emp;
-- group by 给查询的结果分组
-- 注意：select之后的字段名如果没有在group by之后出现，则必须要对该字段进行聚合和处理（即聚合函数）
select country from people group by country; -- 查询表中有哪些国家
-- having语句
-- 作用：对查询的结果进一步筛选
-- 使用注意：
-- having语句通常和group by语句联合使用，过滤由group by语句返回的记录集决定
-- where只能操作表中实际存在的字段，having语句可操作由聚合函数的显示列

-- 多表查询（关联查询，连接查询）
-- 1.笛卡尔积：m*n
select * from emp,dept;

-- 2.内连接：不区分主从表，与连接顺序无关，两张表均满足条件则出现结果集中
select * from emp, dept where emp.deptno=dept.deptno;
-- inner join ... on ...
select * from emp inner join dept on emp.deptno=dept.deptno;
-- inner join ... using ...
select * from emp inner join dept using(deptno);

-- 3.自然连接：俩表中字段名称相等，数据类型相同的字段进行连接，会自动去重重复列（如果有多个字段符合要求，那么他们会被作为自然连接的条件）
select * from emp natural join dept;

-- 4.外连接：有主从表之分，与连接顺序有关。以驱动表为依据，匹配表依次进行查询；匹配表中找不到数据，则以null填充。
-- 左外连接：left join ... on ... ，on也可以换为using()
select * from emp left join dept on emp.deptno = dept.deptno;
select * from emp left join dept using(deptno);
-- 右外连接：right join ... on ... ，on也可以换为using()
select * from emp right join dept on emp.deptno = dept.deptno;
select * from emp right join dept using(deptno);

-- 5.自连接：同一个表里面的数据相关联
--查询所有的员工的姓名和上级领导的姓名  emp(内连接)
select e1.ename ename, e2.ename mgrname from emp e1,emp e2 where e1.mgr=e2.empno;
select e1.ename ename, e2.ename mgrname from emp e1 left join emp e2 on e1.mgr=e2.empno;-- (左连接)


-- 子查询(嵌套查询)
-- 单行子查询：子查询的结果返回一行
select dname from dept where deptno = (select deptno from emp where empno =7788);
-- 多行子查询：查询的结果返回一个集合
select dname from dept where deptno =any(select deptno from emp where sal>2000);
-- =ANY 含义就是in   >any  大于最小值   <any  小于最大值
-- >all 大于最大值    <all 小于最小值
select * from emp e where sal > (select avg(sal) from emp e1 where e1.deptno = e.deptno);

-- in和exists的区别
-- 1.IN
-- 主查询的条件字段和子查询返回字段必须一致。
-- 先执行子查询，将返回子查询的结果给主查询，再执行主查询
-- 2.EXISTS
-- 主查询不需要出现条件字段
-- 先执行主查询，将主查询的表的字段传给子查询，如果在子查询找到相应结果，
-- 返回true,将该结果显示在结果集中。否则返回false
select dname from dept where deptno in (select deptno from emp where sal > 2000);
select dname from dept d where exists(select * from emp e where sal > 2000 and d.deptno = e.deptno);

-- 联合查询
-- 1.union：并集，所有的内容都查询，重复的显示一次
select * from emp where deptno = 30 union select * from emp where sal > 2000;
-- 2.UNION ALL：并集，所有的内容都显示，包括重复的
select * from emp where deptno = 30 union all select * from emp where sal > 2000;

-- 事务指逻辑上的一组操作，组成这组操作的各个单元，要么全成功，要么全不成功。
--  事务的ACID特性
--       原子性：指事务是一个不可分割的工作单位，事务中的操作要么都发生，要么都不发生。 
--       一致性：事务必须使数据库从一个一致性状态变换到另外一个一致性状态。转账前和转账后的总金额不变。
--       隔离性：事务的隔离性是多个用户并发访问数据库时，数据库为每一个用户开启的事务，不能被其他事务的操作数据所干扰，多个并发事务之间要相互隔离。
--       持久性：指一个事务一旦被提交，它对数据库中数据的改变就是永久性的，接下来即使数据库发生故障也不应该对其有任何影响。
--  事务的实现  tcl commit rollback
--         查看事务  show variables like '%autocommit%'
--         a)mysql数据库默认是自动提交
--             set autocommit=0; 不自动提交
--             set autocomiit=1;自动提交
--         b)手动开启事务
--              start transaction/begin;
--         c)手动提交或则回滚
--              commit;
--              rollback;
--              savepoint;保存点，恢复必须在事务提交之前。事务一旦提交，所有的保存点全部失效。
--         注意：DDL操作会隐式事务提交

-- 事物的隔离级别
--     赃读：指一个事务读取了另一个事务未提交的数据。
--     不可重复读：在一个事务内读取表中的某一行数据，多次读取结果不同。一个事务读取到了另一个事务提交后的数据。（update）
--     虚读（幻读）：是指在一个事务内读取到了别的事务插入的数据，导致前后读取不一致。  (insert)
--     数据库通过设置事务的隔离级别防止以上情况的发生：
--         * 1、READ UNCOMMITTED: 赃读、不可重复读、虚读都有可能发生。
--         * 2、READ COMMITTED: 避免赃读。不可重复读、虚读都有可能发生。（oracle默认的）
--         * 4、REPEATABLE READ:避免赃读、不可重复读。虚读有可能发生。（mysql默认）
--         * 8、SERIALIZABLE: 避免赃读、不可重复读、虚读。
--         级别越高，性能越低，数据越安全
-- mysql中：
--   查看当前的事务隔离级别：SELECT @@TX_ISOLATION;
--   更改当前的事务隔离级别：SET TRANSACTION ISOLATION LEVEL 四个级别之一。
--   设置隔离级别必须在事务之前
